home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / AlgoSampObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  42.4 KB  |  1,531 lines  |  [TEXT/KAHL]

  1. /* AlgoSampObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "AlgoSampObject.h"
  31. #include "AlgoSampList.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34. #include "CodeCenter.h"
  35. #include "PcodeStack.h"
  36. #include "PcodeSystem.h"
  37. #include "MainWindowStuff.h"
  38. #include "Alert.h"
  39. #include "Numbers.h"
  40. #include "SampleStorageActual.h"
  41. #include "AlgoSampWindow.h"
  42. #include "CompilerRoot.h"
  43. #include "FunctionCode.h"
  44. #include "BufferedFileInput.h"
  45. #include "BufferedFileOutput.h"
  46.  
  47.  
  48. struct AlgoSampObjectRec
  49.     {
  50.         MyBoolean                                DataModified;
  51.  
  52.         char*                                        Name;
  53.         char*                                        AlgoSampFormula;
  54.  
  55.         MyBoolean                                NeedsToBeRebuilt;
  56.         SampleStorageActualRec*    SampleData; /* NIL if not built */
  57.         NumBitsType                            NumBits;
  58.         NumChannelsType                    NumChannels;
  59.  
  60.         long                                        Origin;
  61.         long                                        LoopStart1;
  62.         long                                        LoopStart2;
  63.         long                                        LoopStart3;
  64.         long                                        LoopEnd1;
  65.         long                                        LoopEnd2;
  66.         long                                        LoopEnd3;
  67.         long                                        SamplingRate;
  68.         double                                    NaturalFrequency;
  69.  
  70.         AlgoSampWindowRec*            AlgoSampWindow;
  71.  
  72.         struct CodeCenterRec*        CodeCenter;
  73.         struct MainWindowRec*        MainWindow;
  74.         AlgoSampListRec*                AlgoSampList;
  75.  
  76.         short                                        SavedWindowXLoc;
  77.         short                                        SavedWindowYLoc;
  78.         short                                        SavedWindowWidth;
  79.         short                                        SavedWindowHeight;
  80.     };
  81.  
  82.  
  83. /* allocate and create a new empty algorithmic sample object, with reasonable defaults */
  84. AlgoSampObjectRec*        NewAlgoSampObject(struct CodeCenterRec* CodeCenter,
  85.                                                 struct MainWindowRec* MainWindow,
  86.                                                 struct AlgoSampListRec* AlgoSampList)
  87.     {
  88.         AlgoSampObjectRec*    AlgoSampObj;
  89.  
  90.         AlgoSampObj = (AlgoSampObjectRec*)AllocPtrCanFail(sizeof(AlgoSampObjectRec),
  91.             "AlgoSampObjectRec");
  92.         if (AlgoSampObj == NIL)
  93.             {
  94.              FailurePoint1:
  95.                 return NIL;
  96.             }
  97.         AlgoSampObj->Name = StringToBlockCopy("untitled");
  98.         if (AlgoSampObj->Name == NIL)
  99.             {
  100.              FailurePoint2:
  101.                 ReleasePtr((char*)AlgoSampObj);
  102.                 goto FailurePoint1;
  103.             }
  104.         AlgoSampObj->AlgoSampFormula = StringToBlockCopy(
  105.             "# samplingrate, origin, loopstart1, loopstart2, loopstart3 : integer\x0a"
  106.             "# loopend1, loopend2, loopend3 : integer\x0a"
  107.             "# naturalfrequency : double; [data | leftdata, rightdata] : fixedarray\x0a");
  108.         if (AlgoSampObj->AlgoSampFormula == NIL)
  109.             {
  110.              FailurePoint3:
  111.                 ReleasePtr(AlgoSampObj->Name);
  112.                 goto FailurePoint2;
  113.             }
  114.         AlgoSampObj->DataModified = False;
  115.         AlgoSampObj->NeedsToBeRebuilt = True;
  116.         AlgoSampObj->SampleData = NIL;
  117.         AlgoSampObj->Origin = 0;
  118.         AlgoSampObj->LoopStart1 = 0;
  119.         AlgoSampObj->LoopStart2 = 0;
  120.         AlgoSampObj->LoopStart3 = 0;
  121.         AlgoSampObj->LoopEnd1 = 0;
  122.         AlgoSampObj->LoopEnd2 = 0;
  123.         AlgoSampObj->LoopEnd3 = 0;
  124.         AlgoSampObj->SamplingRate = 22050;
  125.         AlgoSampObj->NaturalFrequency = 261.625565300598635;
  126.         AlgoSampObj->AlgoSampWindow = NIL;
  127.         AlgoSampObj->CodeCenter = CodeCenter;
  128.         AlgoSampObj->MainWindow = MainWindow;
  129.         AlgoSampObj->AlgoSampList = AlgoSampList;
  130.         AlgoSampObj->NumBits = eSample16bit;
  131.         AlgoSampObj->NumChannels = eSampleMono;
  132.         AlgoSampObj->SavedWindowXLoc = 0;
  133.         AlgoSampObj->SavedWindowYLoc = 0;
  134.         AlgoSampObj->SavedWindowWidth = 0;
  135.         AlgoSampObj->SavedWindowHeight = 0;
  136.         return AlgoSampObj;
  137.     }
  138.  
  139.  
  140. /* dispose of an algorithmic sample object */
  141. void                                    DisposeAlgoSampObject(AlgoSampObjectRec* AlgoSampObj)
  142.     {
  143.         CheckPtrExistence(AlgoSampObj);
  144.         if (AlgoSampObj->AlgoSampWindow != NIL)
  145.             {
  146.                 DisposeAlgoSampWindow(AlgoSampObj->AlgoSampWindow);
  147.                 ERROR(AlgoSampObj->AlgoSampWindow != NIL,PRERR(AllowResume,
  148.                     "DisposeAlgoSampObject:  window thing not NIL after DisposeAlgoSampWindow"));
  149.             }
  150.         ReleasePtr(AlgoSampObj->Name);
  151.         ReleasePtr(AlgoSampObj->AlgoSampFormula);
  152.         if (AlgoSampObj->SampleData != NIL)
  153.             {
  154.                 DisposeSampleStorageActual(AlgoSampObj->SampleData);
  155.             }
  156.         ReleasePtr((char*)AlgoSampObj);
  157.     }
  158.  
  159.  
  160. /* find out if algorithmic sample object has been modified */
  161. MyBoolean                            HasAlgoSampObjectBeenModified(AlgoSampObjectRec* AlgoSampObj)
  162.     {
  163.         CheckPtrExistence(AlgoSampObj);
  164.         if (AlgoSampObj->AlgoSampWindow != NIL)
  165.             {
  166.                 return AlgoSampObj->DataModified
  167.                     || HasAlgoSampWindowBeenModified(AlgoSampObj->AlgoSampWindow);
  168.             }
  169.          else
  170.             {
  171.                 return AlgoSampObj->DataModified;
  172.             }
  173.     }
  174.  
  175.  
  176. static FunctionParamRec        StereoArgList[] =
  177.     {
  178.         {"loopstart1",eInteger},
  179.         {"loopstart2",eInteger},
  180.         {"loopstart3",eInteger},
  181.         {"loopend1",eInteger},
  182.         {"loopend2",eInteger},
  183.         {"loopend3",eInteger},
  184.         {"origin",eInteger},
  185.         {"samplingrate",eInteger},
  186.         {"naturalfrequency",eInteger},
  187.         {"leftdata",eArrayOfFixed},
  188.         {"rightdata",eArrayOfFixed}
  189.     };
  190. #define STEREOARGLISTLENGTH (sizeof(StereoArgList) / sizeof(StereoArgList[0]))
  191.  
  192.  
  193. static FunctionParamRec        MonoArgList[] =
  194.     {
  195.         {"loopstart1",eInteger},
  196.         {"loopstart2",eInteger},
  197.         {"loopstart3",eInteger},
  198.         {"loopend1",eInteger},
  199.         {"loopend2",eInteger},
  200.         {"loopend3",eInteger},
  201.         {"origin",eInteger},
  202.         {"samplingrate",eInteger},
  203.         {"naturalfrequency",eInteger},
  204.         {"data",eArrayOfFixed}
  205.     };
  206. #define MONOARGLISTLENGTH (sizeof(MonoArgList) / sizeof(MonoArgList[0]))
  207.  
  208.  
  209. /* build the algorithmic sample.  returns True if successful. */
  210. MyBoolean                            AlgoSampObjectBuild(AlgoSampObjectRec* AlgoSampObj)
  211.     {
  212.         char*                                Blob;
  213.         PcodeRec*                        FuncCode;
  214.         CompileErrors                Error;
  215.         long                                LineNumber;
  216.         ParamStackRec*            ParamList;
  217.         EvalErrors                    OtherError;
  218.         OpcodeRec*                    ErrorOpcode;
  219.         long                                OffendingInstruction;
  220.         DataTypes                        ReturnType;
  221.  
  222.         CheckPtrExistence(AlgoSampObj);
  223.  
  224.         /* make sure we are unbuilt */
  225.         AlgoSampObjectUnbuild(AlgoSampObj);
  226.         ERROR(AlgoSampObj->SampleData != NIL,PRERR(ForceAbort,
  227.             "AlgoSampObjectBuild:  called AlgoSampObjectUnbuild but object still exists"));
  228.  
  229.         /* bring the world up to date */
  230.         if (!MainWindowMakeUpToDateFunctions(AlgoSampObj->MainWindow))
  231.             {
  232.                 return False;
  233.             }
  234.  
  235.         /* prepare the text blob to be evaluated */
  236.         Blob = AlgoSampObjectGetFormulaCopy(AlgoSampObj);
  237.         if (Blob == NIL)
  238.             {
  239.              FailurePoint1:
  240.                 AlertHalt("There is not enough memory available to compile the algorithmic "
  241.                     "sample generator function.",NIL);
  242.                 return False;
  243.             }
  244.  
  245.         /* perform compilation */
  246.         Error = CompileSpecialFunction((AlgoSampObjectGetNumChannels(AlgoSampObj)
  247.             == eSampleStereo) ? StereoArgList : MonoArgList,(AlgoSampObjectGetNumChannels(
  248.             AlgoSampObj) == eSampleStereo) ? STEREOARGLISTLENGTH : MONOARGLISTLENGTH,
  249.             &LineNumber,&ReturnType,Blob,&FuncCode);
  250.         ReleasePtr(Blob);
  251.         /* show the error message if there is one */
  252.         if (Error != eCompileNoError)
  253.             {
  254.                 if (!AlgoSampObjectOpenWindow(AlgoSampObj))
  255.                     {
  256.                         AlertHalt("A compile error occurred but there is not enough memory "
  257.                             "available to display the error message.",NIL);
  258.                         return False;
  259.                     }
  260.                 AlgoSampWindowHiliteLine(AlgoSampObj->AlgoSampWindow,LineNumber - 1);
  261.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  262.                 return False;
  263.             }
  264.  
  265.         /* try to evaluate the code */
  266.         ParamList = NewParamStack();
  267.         if (ParamList == NIL)
  268.             {
  269.              SecondFailurePoint1:
  270.                 DisposePcode(FuncCode);
  271.                 AlertHalt("There is not enough memory available to evaluate the algorithmic "
  272.                     "sample generator function.",NIL);
  273.                 return False;
  274.             }
  275.         /* add a space for the return value */
  276.         if (!AddIntegerToStack(ParamList,0))
  277.             {
  278.              SecondFailurePoint2:
  279.                 DisposeParamStack(ParamList);
  280.                 goto SecondFailurePoint1;
  281.             }
  282.         /* add the special parameters (SymbolStack order MUST be the same */
  283.         /* order as that used for the Parameterlist) */
  284.         /* loopstart */
  285.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart1(AlgoSampObj)))
  286.             {
  287.                 goto SecondFailurePoint2;
  288.             }
  289.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart2(AlgoSampObj)))
  290.             {
  291.                 goto SecondFailurePoint2;
  292.             }
  293.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopStart3(AlgoSampObj)))
  294.             {
  295.                 goto SecondFailurePoint2;
  296.             }
  297.         /* loopend */
  298.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd1(AlgoSampObj)))
  299.             {
  300.                 goto SecondFailurePoint2;
  301.             }
  302.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd2(AlgoSampObj)))
  303.             {
  304.                 goto SecondFailurePoint2;
  305.             }
  306.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetLoopEnd3(AlgoSampObj)))
  307.             {
  308.                 goto SecondFailurePoint2;
  309.             }
  310.         /* origin */
  311.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetOrigin(AlgoSampObj)))
  312.             {
  313.                 goto SecondFailurePoint2;
  314.             }
  315.         /* samplingrate */
  316.         if (!AddIntegerToStack(ParamList,AlgoSampObjectGetSamplingRate(AlgoSampObj)))
  317.             {
  318.                 goto SecondFailurePoint2;
  319.             }
  320.         /* basefrequency */
  321.         if (!AddDoubleToStack(ParamList,AlgoSampObjectGetNaturalFrequency(AlgoSampObj)))
  322.             {
  323.                 goto SecondFailurePoint2;
  324.             }
  325.         /* data */
  326.         if (AlgoSampObjectGetNumChannels(AlgoSampObj) == eSampleStereo)
  327.             {
  328.                 char*                    Buffer;
  329.  
  330.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  331.                 if (Buffer == NIL)
  332.                     {
  333.                         goto SecondFailurePoint2;
  334.                     }
  335.                 if (!AddArrayToStack(ParamList,Buffer))
  336.                     {
  337.                         ReleasePtr(Buffer);
  338.                         goto SecondFailurePoint2;
  339.                     }
  340.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  341.                 if (Buffer == NIL)
  342.                     {
  343.                         goto SecondFailurePoint2;
  344.                     }
  345.                 if (!AddArrayToStack(ParamList,Buffer))
  346.                     {
  347.                         ReleasePtr(Buffer);
  348.                         goto SecondFailurePoint2;
  349.                     }
  350.             }
  351.          else
  352.             {
  353.                 char*                    Buffer;
  354.  
  355.                 Buffer = AllocPtrCanFail(0,"degeneratesample");
  356.                 if (Buffer == NIL)
  357.                     {
  358.                         goto SecondFailurePoint2;
  359.                     }
  360.                 if (!AddArrayToStack(ParamList,Buffer))
  361.                     {
  362.                         ReleasePtr(Buffer);
  363.                         goto SecondFailurePoint2;
  364.                     }
  365.             }
  366.  
  367.         /* executing the actual code */
  368.         OtherError = EvaluatePcode(ParamList,FuncCode,
  369.             AlgoSampObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,AlgoSampObj->MainWindow,
  370.             &MainWindowGetSampleLeftCopy,&MainWindowGetSampleRightCopy,
  371.             &MainWindowGetSampleMonoCopy,&MainWindowGetWaveTableFrameCount,
  372.             &MainWindowGetWaveTableTableCount,&MainWindowGetWaveTableArray);
  373.         DisposePcode(FuncCode);
  374.         if (OtherError != eEvalNoError)
  375.             {
  376.                 char*                    FuncNameString;
  377.                 FuncCodeRec*    ErrorFunction;
  378.                 MyBoolean            SuccessFlag;
  379.  
  380.                 /* present error message */
  381.                 AlgoSampObjectOpenWindow(AlgoSampObj);
  382.                 SuccessFlag = False;
  383.                 ErrorFunction = GetFunctionFromOpcode(AlgoSampObj->CodeCenter,ErrorOpcode);
  384.                 if (ErrorFunction == NIL)
  385.                     {
  386.                         FuncNameString = StringToBlockCopy("<anonymous>");
  387.                     }
  388.                  else
  389.                     {
  390.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  391.                     }
  392.                 if (FuncNameString != NIL)
  393.                     {
  394.                         char*                    Key;
  395.  
  396.                         Key = StringToBlockCopy("_");
  397.                         if (Key != NIL)
  398.                             {
  399.                                 char*                    BaseMessage;
  400.  
  401.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  402.                                 if (BaseMessage != NIL)
  403.                                     {
  404.                                         char*                    FixedMessage1;
  405.  
  406.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  407.                                         if (FixedMessage1 != NIL)
  408.                                             {
  409.                                                 char*                    NumberStr;
  410.  
  411.                                                 NumberStr = IntegerToString(OffendingInstruction);
  412.                                                 if (NumberStr != NIL)
  413.                                                     {
  414.                                                         char*                    FixedMessage2;
  415.  
  416.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  417.                                                         if (FixedMessage2 != NIL)
  418.                                                             {
  419.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  420.                                                                 SuccessFlag = True;
  421.                                                                 ReleasePtr(FixedMessage2);
  422.                                                             }
  423.                                                         ReleasePtr(NumberStr);
  424.                                                     }
  425.                                                 ReleasePtr(FixedMessage1);
  426.                                             }
  427.                                         ReleasePtr(BaseMessage);
  428.                                     }
  429.                                 ReleasePtr(Key);
  430.                             }
  431.                         ReleasePtr(FuncNameString);
  432.                     }
  433.                 if (!SuccessFlag)
  434.                     {
  435.                         AlertHalt("There is not enough memory available to show the "
  436.                             "compile error message.",NIL);
  437.                     }
  438.                 DisposeParamStack(ParamList);
  439.                 return False;
  440.             }
  441.  
  442.         /* add the new data */
  443.         if (AlgoSampObjectGetNumChannels(AlgoSampObj) == eSampleStereo)
  444.             {
  445.                 largefixedsigned*                    Left;
  446.                 largefixedsigned*                    Right;
  447.                 long                                            Limit;
  448.                 long                                            Scan;
  449.  
  450.                 Left = (largefixedsigned*)GetStackArray(ParamList,10);
  451.                 Right = (largefixedsigned*)GetStackArray(ParamList,11);
  452.                 if ((Left == NIL) || (Right == NIL))
  453.                     {
  454.                         AlertHalt("NIL array returned from function building algorithmic sample.",NIL);
  455.                      StereoRebuildFailurePoint1:
  456.                         DisposeParamStack(ParamList);
  457.                         AlgoSampObjectOpenWindow(AlgoSampObj);
  458.                         return False;
  459.                     }
  460.                 if (PtrSize((char*)Left) != PtrSize((char*)Right))
  461.                     {
  462.                         AlertHalt("Left and Right algorithmic sample arrays are not the same size.",NIL);
  463.                      StereoRebuildFailurePoint2:
  464.                         goto StereoRebuildFailurePoint1;
  465.                     }
  466.                 ERROR(PtrSize((char*)Left) % sizeof(largefixedsigned) != 0,
  467.                     PRERR(ForceAbort,"AlgoSampObjectBuild:  array alignment error"));
  468.                 Limit = PtrSize((char*)Left) / sizeof(largefixedsigned);
  469.                 AlgoSampObj->SampleData = NewSampleStorageActual(AlgoSampObjectGetNumBits(
  470.                     AlgoSampObj),eSampleStereo,Limit);
  471.                 if (AlgoSampObj->SampleData == NIL)
  472.                     {
  473.                         AlertHalt("There is not enough memory available to build "
  474.                             "the algorithmic sample.",NIL);
  475.                      StereoRebuildFailurePoint3:
  476.                         goto StereoRebuildFailurePoint2;
  477.                     }
  478.                 for (Scan = 0; Scan < Limit; Scan += 1)
  479.                     {
  480.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  481.                             eLeftChannel,Left[Scan]);
  482.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  483.                             eRightChannel,Right[Scan]);
  484.                     }
  485.             }
  486.          else
  487.             {
  488.                 largefixedsigned*                    Middle;
  489.                 long                                            Limit;
  490.                 long                                            Scan;
  491.  
  492.                 Middle = (largefixedsigned*)GetStackArray(ParamList,10);
  493.                 if (Middle == NIL)
  494.                     {
  495.                         AlertHalt("NIL array returned from function building algorithmic sample.",NIL);
  496.                      MonoRebuildFailurePoint1:
  497.                         DisposeParamStack(ParamList);
  498.                         AlgoSampObjectOpenWindow(AlgoSampObj);
  499.                         return False;
  500.                     }
  501.                 ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
  502.                     PRERR(ForceAbort,"AlgoSampObjectBuild:  array alignment error"));
  503.                 Limit = PtrSize((char*)Middle) / sizeof(largefixedsigned);
  504.                 AlgoSampObj->SampleData = NewSampleStorageActual(AlgoSampObjectGetNumBits(
  505.                     AlgoSampObj),eSampleMono,Limit);
  506.                 if (AlgoSampObj->SampleData == NIL)
  507.                     {
  508.                         AlertHalt("There is not enough memory available to build "
  509.                             "the algorithmic sample.",NIL);
  510.                      MonoRebuildFailurePoint2:
  511.                         goto MonoRebuildFailurePoint1;
  512.                     }
  513.                 for (Scan = 0; Scan < Limit; Scan += 1)
  514.                     {
  515.                         SetSampleStorageActualValue(AlgoSampObj->SampleData,Scan,
  516.                             eMonoChannel,Middle[Scan]);
  517.                     }
  518.             }
  519.         DisposeParamStack(ParamList);
  520.         AlgoSampObj->NeedsToBeRebuilt = False;
  521.         return True;
  522.     }
  523.  
  524.  
  525. /* unconditionally unbuild the algorithmic sample */
  526. void                                    AlgoSampObjectUnbuild(AlgoSampObjectRec* AlgoSampObj)
  527.     {
  528.         CheckPtrExistence(AlgoSampObj);
  529.         if (AlgoSampObj->SampleData != NIL)
  530.             {
  531.                 DisposeSampleStorageActual(AlgoSampObj->SampleData);
  532.                 AlgoSampObj->SampleData = NIL;
  533.             }
  534.     }
  535.  
  536.  
  537. /* build the algorithmic sample if necessary.  return True if successful. */
  538. MyBoolean                            AlgoSampObjectMakeUpToDate(AlgoSampObjectRec* AlgoSampObj)
  539.     {
  540.         CheckPtrExistence(AlgoSampObj);
  541.         if ((AlgoSampObj->SampleData == NIL) || (AlgoSampObj->NeedsToBeRebuilt)
  542.             || (AlgoSampObj->AlgoSampWindow != NIL))
  543.             {
  544.                 return AlgoSampObjectBuild(AlgoSampObj);
  545.             }
  546.          else
  547.             {
  548.                 return True;
  549.             }
  550.     }
  551.  
  552.  
  553. /* get a copy of the algorithmic sample's name. */
  554. char*                                    AlgoSampObjectGetNameCopy(AlgoSampObjectRec* AlgoSampObj)
  555.     {
  556.         char*                                NameTemp;
  557.  
  558.         CheckPtrExistence(AlgoSampObj);
  559.         if (AlgoSampObj->AlgoSampWindow != NIL)
  560.             {
  561.                 NameTemp = AlgoSampWindowGetNameCopy(AlgoSampObj->AlgoSampWindow);
  562.             }
  563.          else
  564.             {
  565.                 NameTemp = CopyPtr(AlgoSampObj->Name);
  566.             }
  567.         if (NameTemp != NIL)
  568.             {
  569.                 SetTag(NameTemp,"AlgoSampNameCopy");
  570.             }
  571.         return NameTemp;
  572.     }
  573.  
  574.  
  575. /* set the algorithmic sample's name.  the object becomes the owner of the Name */
  576. /* block so the caller should not release it. */
  577. void                                    AlgoSampObjectNewName(AlgoSampObjectRec* AlgoSampObj, char* Name)
  578.     {
  579.         CheckPtrExistence(AlgoSampObj);
  580.         CheckPtrExistence(Name);
  581.         ReleasePtr(AlgoSampObj->Name);
  582.         SetTag(Name,"AlgoSampName");
  583.         AlgoSampObj->Name = Name;
  584.         AlgoSampObj->DataModified = True;
  585.         AlgoSampObj->NeedsToBeRebuilt = True;
  586.         AlgoSampListAlgoSampNameChanged(AlgoSampObj->AlgoSampList,AlgoSampObj);
  587.     }
  588.  
  589.  
  590. /* get a copy of the formula that generates the algorithmic sample */
  591. char*                                    AlgoSampObjectGetFormulaCopy(AlgoSampObjectRec* AlgoSampObj)
  592.     {
  593.         char*                                TextCopy;
  594.  
  595.         CheckPtrExistence(AlgoSampObj);
  596.         if (AlgoSampObj->AlgoSampWindow != NIL)
  597.             {
  598.                 TextCopy = AlgoSampWindowGetFormulaCopy(AlgoSampObj->AlgoSampWindow);
  599.             }
  600.          else
  601.             {
  602.                 TextCopy = CopyPtr(AlgoSampObj->AlgoSampFormula);
  603.             }
  604.         if (TextCopy != NIL)
  605.             {
  606.                 SetTag(TextCopy,"AlgoSampFormulaCopy");
  607.             }
  608.         return TextCopy;
  609.     }
  610.  
  611.  
  612. /* install a new formula into the algorithmic sample.  the object becomes the owner */
  613. /* of the formula, so the caller should not release it */
  614. void                                    AlgoSampObjectNewFormula(AlgoSampObjectRec* AlgoSampObj,
  615.                                                 char* Formula)
  616.     {
  617.         CheckPtrExistence(AlgoSampObj);
  618.         CheckPtrExistence(Formula);
  619.         ReleasePtr(AlgoSampObj->AlgoSampFormula);
  620.         SetTag(Formula,"AlgoSampFormula");
  621.         AlgoSampObj->AlgoSampFormula = Formula;
  622.         AlgoSampObj->DataModified = True;
  623.         AlgoSampObj->NeedsToBeRebuilt = True;
  624.     }
  625.  
  626.  
  627. /* get the number of bits in a channel for the algorithmic sample */
  628. NumBitsType                        AlgoSampObjectGetNumBits(AlgoSampObjectRec* AlgoSampObj)
  629.     {
  630.         CheckPtrExistence(AlgoSampObj);
  631.         if (AlgoSampObj->AlgoSampWindow != NIL)
  632.             {
  633.                 return AlgoSampWindowGetNumBits(AlgoSampObj->AlgoSampWindow);
  634.             }
  635.          else
  636.             {
  637.                 return AlgoSampObj->NumBits;
  638.             }
  639.     }
  640.  
  641.  
  642. /* change the number of bits in a channel for the algorithmic sample */
  643. void                                    AlgoSampObjectPutNumBits(AlgoSampObjectRec* AlgoSampObj,
  644.                                                 NumBitsType NewNumBits)
  645.     {
  646.         CheckPtrExistence(AlgoSampObj);
  647.         AlgoSampObjectUnbuild(AlgoSampObj);
  648.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  649.             PRERR(ForceAbort,"AlgoSampObjectPutNumBits:  bad value"));
  650.         AlgoSampObj->NumBits = NewNumBits;
  651.         AlgoSampObj->DataModified = True;
  652.         AlgoSampObj->NeedsToBeRebuilt = True;
  653.     }
  654.  
  655.  
  656. /* get the number of channels in the algorithmic sample */
  657. NumChannelsType                AlgoSampObjectGetNumChannels(AlgoSampObjectRec* AlgoSampObj)
  658.     {
  659.         CheckPtrExistence(AlgoSampObj);
  660.         if (AlgoSampObj->AlgoSampWindow != NIL)
  661.             {
  662.                 return AlgoSampWindowGetNumChannels(AlgoSampObj->AlgoSampWindow);
  663.             }
  664.          else
  665.             {
  666.                 return AlgoSampObj->NumChannels;
  667.             }
  668.     }
  669.  
  670.  
  671. /* change the number of channels for the algorithmic sample */
  672. void                                    AlgoSampObjectPutNumChannels(AlgoSampObjectRec* AlgoSampObj,
  673.                                                 NumChannelsType NewNumChannels)
  674.     {
  675.         CheckPtrExistence(AlgoSampObj);
  676.         AlgoSampObjectUnbuild(AlgoSampObj);
  677.         ERROR((NewNumChannels != eSampleMono) && (NewNumChannels != eSampleStereo),
  678.             PRERR(ForceAbort,"AlgoSampObjectPutNumChannels:  bad value"));
  679.         AlgoSampObj->NumChannels = NewNumChannels;
  680.         AlgoSampObj->DataModified = True;
  681.         AlgoSampObj->NeedsToBeRebuilt = True;
  682.     }
  683.  
  684.  
  685. /* get the number of data frames in the algorithmic sample */
  686. long                                    AlgoSampObjetGetNumFrames(AlgoSampObjectRec* AlgoSampObj)
  687.     {
  688.         CheckPtrExistence(AlgoSampObj);
  689.         ERROR(AlgoSampObj->SampleData == NIL,PRERR(ForceAbort,
  690.             "AlgoSampObjetGetNumFrames:  sample data has not been built"));
  691.         return GetSampleStorageActualNumFrames(AlgoSampObj->SampleData);
  692.     }
  693.  
  694.  
  695. long                                    AlgoSampObjectGetOrigin(AlgoSampObjectRec* AlgoSampObj)
  696.     {
  697.         CheckPtrExistence(AlgoSampObj);
  698.         if (AlgoSampObj->AlgoSampWindow != NIL)
  699.             {
  700.                 return AlgoSampWindowGetOrigin(AlgoSampObj->AlgoSampWindow);
  701.             }
  702.          else
  703.             {
  704.                 return AlgoSampObj->Origin;
  705.             }
  706.     }
  707.  
  708.  
  709. long                                    AlgoSampObjectGetLoopStart1(AlgoSampObjectRec* AlgoSampObj)
  710.     {
  711.         CheckPtrExistence(AlgoSampObj);
  712.         if (AlgoSampObj->AlgoSampWindow != NIL)
  713.             {
  714.                 return AlgoSampWindowGetLoopStart1(AlgoSampObj->AlgoSampWindow);
  715.             }
  716.          else
  717.             {
  718.                 return AlgoSampObj->LoopStart1;
  719.             }
  720.     }
  721.  
  722.  
  723. long                                    AlgoSampObjectGetLoopStart2(AlgoSampObjectRec* AlgoSampObj)
  724.     {
  725.         CheckPtrExistence(AlgoSampObj);
  726.         if (AlgoSampObj->AlgoSampWindow != NIL)
  727.             {
  728.                 return AlgoSampWindowGetLoopStart2(AlgoSampObj->AlgoSampWindow);
  729.             }
  730.          else
  731.             {
  732.                 return AlgoSampObj->LoopStart2;
  733.             }
  734.     }
  735.  
  736.  
  737. long                                    AlgoSampObjectGetLoopStart3(AlgoSampObjectRec* AlgoSampObj)
  738.     {
  739.         CheckPtrExistence(AlgoSampObj);
  740.         if (AlgoSampObj->AlgoSampWindow != NIL)
  741.             {
  742.                 return AlgoSampWindowGetLoopStart3(AlgoSampObj->AlgoSampWindow);
  743.             }
  744.          else
  745.             {
  746.                 return AlgoSampObj->LoopStart3;
  747.             }
  748.     }
  749.  
  750.  
  751. long                                    AlgoSampObjectGetLoopEnd1(AlgoSampObjectRec* AlgoSampObj)
  752.     {
  753.         CheckPtrExistence(AlgoSampObj);
  754.         if (AlgoSampObj->AlgoSampWindow != NIL)
  755.             {
  756.                 return AlgoSampWindowGetLoopEnd1(AlgoSampObj->AlgoSampWindow);
  757.             }
  758.          else
  759.             {
  760.                 return AlgoSampObj->LoopEnd1;
  761.             }
  762.     }
  763.  
  764.  
  765. long                                    AlgoSampObjectGetLoopEnd2(AlgoSampObjectRec* AlgoSampObj)
  766.     {
  767.         CheckPtrExistence(AlgoSampObj);
  768.         if (AlgoSampObj->AlgoSampWindow != NIL)
  769.             {
  770.                 return AlgoSampWindowGetLoopEnd2(AlgoSampObj->AlgoSampWindow);
  771.             }
  772.          else
  773.             {
  774.                 return AlgoSampObj->LoopEnd2;
  775.             }
  776.     }
  777.  
  778.  
  779. long                                    AlgoSampObjectGetLoopEnd3(AlgoSampObjectRec* AlgoSampObj)
  780.     {
  781.         CheckPtrExistence(AlgoSampObj);
  782.         if (AlgoSampObj->AlgoSampWindow != NIL)
  783.             {
  784.                 return AlgoSampWindowGetLoopEnd3(AlgoSampObj->AlgoSampWindow);
  785.             }
  786.          else
  787.             {
  788.                 return AlgoSampObj->LoopEnd3;
  789.             }
  790.     }
  791.  
  792.  
  793. long                                    AlgoSampObjectGetSamplingRate(AlgoSampObjectRec* AlgoSampObj)
  794.     {
  795.         CheckPtrExistence(AlgoSampObj);
  796.         if (AlgoSampObj->AlgoSampWindow != NIL)
  797.             {
  798.                 return AlgoSampWindowGetSamplingRate(AlgoSampObj->AlgoSampWindow);
  799.             }
  800.          else
  801.             {
  802.                 return AlgoSampObj->SamplingRate;
  803.             }
  804.     }
  805.  
  806.  
  807. double                                AlgoSampObjectGetNaturalFrequency(AlgoSampObjectRec* AlgoSampObj)
  808.     {
  809.         CheckPtrExistence(AlgoSampObj);
  810.         if (AlgoSampObj->AlgoSampWindow != NIL)
  811.             {
  812.                 return AlgoSampWindowGetNaturalFrequency(AlgoSampObj->AlgoSampWindow);
  813.             }
  814.          else
  815.             {
  816.                 return AlgoSampObj->NaturalFrequency;
  817.             }
  818.     }
  819.  
  820.  
  821. char*                                    AlgoSampObjectGetRawData(AlgoSampObjectRec* AlgoSampObj)
  822.     {
  823.         CheckPtrExistence(AlgoSampObj);
  824.         if ((AlgoSampObj->SampleData == NIL) || AlgoSampObj->NeedsToBeRebuilt)
  825.             {
  826.                 return NIL;
  827.             }
  828.         return GetSampleStorageActualRawData(AlgoSampObj->SampleData);
  829.     }
  830.  
  831.  
  832. void                                    AlgoSampObjectPutOrigin(AlgoSampObjectRec* AlgoSampObj,
  833.                                                 long Origin)
  834.     {
  835.         CheckPtrExistence(AlgoSampObj);
  836.         AlgoSampObj->Origin = Origin;
  837.         AlgoSampObj->DataModified = True;
  838.         AlgoSampObj->NeedsToBeRebuilt = True;
  839.     }
  840.  
  841.  
  842. void                                    AlgoSampObjectPutLoopStart1(AlgoSampObjectRec* AlgoSampObj,
  843.                                                 long LoopStart)
  844.     {
  845.         CheckPtrExistence(AlgoSampObj);
  846.         AlgoSampObj->LoopStart1 = LoopStart;
  847.         AlgoSampObj->DataModified = True;
  848.         AlgoSampObj->NeedsToBeRebuilt = True;
  849.     }
  850.  
  851.  
  852. void                                    AlgoSampObjectPutLoopStart2(AlgoSampObjectRec* AlgoSampObj,
  853.                                                 long LoopStart)
  854.     {
  855.         CheckPtrExistence(AlgoSampObj);
  856.         AlgoSampObj->LoopStart2 = LoopStart;
  857.         AlgoSampObj->DataModified = True;
  858.         AlgoSampObj->NeedsToBeRebuilt = True;
  859.     }
  860.  
  861.  
  862. void                                    AlgoSampObjectPutLoopStart3(AlgoSampObjectRec* AlgoSampObj,
  863.                                                 long LoopStart)
  864.     {
  865.         CheckPtrExistence(AlgoSampObj);
  866.         AlgoSampObj->LoopStart3 = LoopStart;
  867.         AlgoSampObj->DataModified = True;
  868.         AlgoSampObj->NeedsToBeRebuilt = True;
  869.     }
  870.  
  871.  
  872. void                                    AlgoSampObjectPutLoopEnd1(AlgoSampObjectRec* AlgoSampObj,
  873.                                                 long LoopEnd)
  874.     {
  875.         CheckPtrExistence(AlgoSampObj);
  876.         AlgoSampObj->LoopEnd1 = LoopEnd;
  877.         AlgoSampObj->DataModified = True;
  878.         AlgoSampObj->NeedsToBeRebuilt = True;
  879.     }
  880.  
  881.  
  882. void                                    AlgoSampObjectPutLoopEnd2(AlgoSampObjectRec* AlgoSampObj,
  883.                                                 long LoopEnd)
  884.     {
  885.         CheckPtrExistence(AlgoSampObj);
  886.         AlgoSampObj->LoopEnd2 = LoopEnd;
  887.         AlgoSampObj->DataModified = True;
  888.         AlgoSampObj->NeedsToBeRebuilt = True;
  889.     }
  890.  
  891.  
  892. void                                    AlgoSampObjectPutLoopEnd3(AlgoSampObjectRec* AlgoSampObj,
  893.                                                 long LoopEnd)
  894.     {
  895.         CheckPtrExistence(AlgoSampObj);
  896.         AlgoSampObj->LoopEnd3 = LoopEnd;
  897.         AlgoSampObj->DataModified = True;
  898.         AlgoSampObj->NeedsToBeRebuilt = True;
  899.     }
  900.  
  901.  
  902. void                                    AlgoSampObjectPutSamplingRate(AlgoSampObjectRec* AlgoSampObj,
  903.                                                 long SamplingRate)
  904.     {
  905.         CheckPtrExistence(AlgoSampObj);
  906.         if (SamplingRate < MINSAMPLINGRATE)
  907.             {
  908.                 SamplingRate = MINSAMPLINGRATE;
  909.             }
  910.         if (SamplingRate > MAXSAMPLINGRATE)
  911.             {
  912.                 SamplingRate = MAXSAMPLINGRATE;
  913.             }
  914.         AlgoSampObj->SamplingRate = SamplingRate;
  915.         AlgoSampObj->DataModified = True;
  916.         AlgoSampObj->NeedsToBeRebuilt = True;
  917.     }
  918.  
  919.  
  920. void                                    AlgoSampObjectPutNaturalFrequency(AlgoSampObjectRec* AlgoSampObj,
  921.                                                 double NaturalFrequency)
  922.     {
  923.         CheckPtrExistence(AlgoSampObj);
  924.         if (NaturalFrequency < MINNATURALFREQ)
  925.             {
  926.                 NaturalFrequency = MINNATURALFREQ;
  927.             }
  928.         if (NaturalFrequency > MAXNATURALFREQ)
  929.             {
  930.                 NaturalFrequency = MAXNATURALFREQ;
  931.             }
  932.         AlgoSampObj->NaturalFrequency = NaturalFrequency;
  933.         AlgoSampObj->DataModified = True;
  934.         AlgoSampObj->NeedsToBeRebuilt = True;
  935.     }
  936.  
  937.  
  938. /* call which makes object open its editor window */
  939. MyBoolean                            AlgoSampObjectOpenWindow(AlgoSampObjectRec* AlgoSampObj)
  940.     {
  941.         CheckPtrExistence(AlgoSampObj);
  942.         if (AlgoSampObj->AlgoSampWindow == NIL)
  943.             {
  944.                 AlgoSampObj->AlgoSampWindow = NewAlgoSampWindow(AlgoSampObj->MainWindow,
  945.                     AlgoSampObj,AlgoSampObj->AlgoSampList,AlgoSampObj->SavedWindowXLoc,
  946.                     AlgoSampObj->SavedWindowYLoc,AlgoSampObj->SavedWindowWidth,
  947.                     AlgoSampObj->SavedWindowHeight);
  948.             }
  949.          else
  950.             {
  951.                 AlgoSampWindowBringToTop(AlgoSampObj->AlgoSampWindow);
  952.             }
  953.         return (AlgoSampObj->AlgoSampWindow != NIL);
  954.     }
  955.  
  956.  
  957. /* this is called by the window when it is closing to notify the object. */
  958. /* the object should not take any action. */
  959. void                                    AlgoSampObjectClosingWindowNotify(AlgoSampObjectRec* AlgoSampObj,
  960.                                                 short NewX, short NewY, short NewWidth, short NewHeight)
  961.     {
  962.         CheckPtrExistence(AlgoSampObj);
  963.         ERROR(AlgoSampObj->AlgoSampWindow == NIL,PRERR(ForceAbort,
  964.             "AlgoSampObjectClosingWindowNotify:  window not open"));
  965.         AlgoSampObj->AlgoSampWindow = NIL;
  966.         AlgoSampObj->SavedWindowXLoc = NewX;
  967.         AlgoSampObj->SavedWindowYLoc = NewY;
  968.         AlgoSampObj->SavedWindowWidth = NewWidth;
  969.         AlgoSampObj->SavedWindowHeight = NewHeight;
  970.     }
  971.  
  972.  
  973. /* the document's name has changed, so the windows need to be updated */
  974. void                                    AlgoSampObjectGlobalNameChange(AlgoSampObjectRec* AlgoSampObj,
  975.                                                 char* NewFilename)
  976.     {
  977.         CheckPtrExistence(AlgoSampObj);
  978.         if (AlgoSampObj->AlgoSampWindow != NIL)
  979.             {
  980.                 AlgoSampWindowGlobalNameChange(AlgoSampObj->AlgoSampWindow,NewFilename);
  981.             }
  982.     }
  983.  
  984.  
  985. /* Algorithmic Sample Object Subblock Format: */
  986. /*   1-byte format version number */
  987. /*       should be 1 */
  988. /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  989. /*   2-bytes little endian window Y location */
  990. /*   2-bytes little endian window width */
  991. /*   2-bytes little endian window height */
  992. /*   4-bytes little endian name length descriptor */
  993. /*   n-bytes name string (line feed = 0x0a) */
  994. /*   4-bytes little endian formula length descriptor */
  995. /*   n-bytes formula string (line feed = 0x0a) */
  996. /*   1-byte number of bits */
  997. /*       should be 8 or 16 */
  998. /*   1-byte number of channels */
  999. /*       1 = mono */
  1000. /*       2 = stereo */
  1001. /*   4-bytes little endian sample origin */
  1002. /*   4-bytes little endian loop 1 start point */
  1003. /*   4-bytes little endian loop 1 end point */
  1004. /*   4-bytes little endian loop 2 start point */
  1005. /*   4-bytes little endian loop 2 end point */
  1006. /*   4-bytes little endian loop 3 start point */
  1007. /*   4-bytes little endian loop 3 end point */
  1008. /*   4-bytes little endian sampling rate */
  1009. /*       should be between 100 and 65535 */
  1010. /*   4-byte little endian natural frequency fractional portion */
  1011. /*       unsigned; divide by 2^32 to get the actual fraction */
  1012. /*   4-byte little endian natural frequency integer portion */
  1013. /*       total natural frequency should be between 0.01 and 1e6 */
  1014.  
  1015.  
  1016. /* read from the file and create a new algorithmic sample object from it. */
  1017. FileLoadingErrors            AlgoSampObjectNewFromFile(AlgoSampObjectRec** ObjectOut,
  1018.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  1019.                                                 struct MainWindowRec* MainWindow,
  1020.                                                 struct AlgoSampListRec* AlgoSampList)
  1021.     {
  1022.         unsigned char                UnsignedChar;
  1023.         signed short                SignedShort;
  1024.         AlgoSampObjectRec*    AlgoSampObj;
  1025.         FileLoadingErrors        Error;
  1026.         signed long                    SignedLong;
  1027.         unsigned long                UnsignedLong;
  1028.  
  1029.         CheckPtrExistence(Input);
  1030.         CheckPtrExistence(CodeCenter);
  1031.         CheckPtrExistence(MainWindow);
  1032.         CheckPtrExistence(AlgoSampList);
  1033.  
  1034.         AlgoSampObj = (AlgoSampObjectRec*)AllocPtrCanFail(sizeof(AlgoSampObjectRec),
  1035.             "AlgoSampObjectRec");
  1036.         if (AlgoSampObj == NIL)
  1037.             {
  1038.                 Error = eFileLoadOutOfMemory;
  1039.              FailurePoint1:
  1040.                 return Error;
  1041.             }
  1042.  
  1043.         /*   1-byte format version number */
  1044.         /*       should be 1 */
  1045.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1046.             {
  1047.                 Error = eFileLoadDiskError;
  1048.              FailurePoint2:
  1049.                 ReleasePtr((char*)AlgoSampObj);
  1050.                 goto FailurePoint1;
  1051.             }
  1052.  
  1053.         /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  1054.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1055.             {
  1056.                 Error = eFileLoadDiskError;
  1057.              FailurePoint3:
  1058.                 goto FailurePoint2;
  1059.             }
  1060.         AlgoSampObj->SavedWindowXLoc = SignedShort;
  1061.  
  1062.         /*   2-bytes little endian window Y location */
  1063.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1064.             {
  1065.                 Error = eFileLoadDiskError;
  1066.              FailurePoint4:
  1067.                 goto FailurePoint3;
  1068.             }
  1069.         AlgoSampObj->SavedWindowYLoc = SignedShort;
  1070.  
  1071.         /*   2-bytes little endian window width */
  1072.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1073.             {
  1074.                 Error = eFileLoadDiskError;
  1075.              FailurePoint5:
  1076.                 goto FailurePoint4;
  1077.             }
  1078.         AlgoSampObj->SavedWindowWidth = SignedShort;
  1079.  
  1080.         /*   2-bytes little endian window height */
  1081.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  1082.             {
  1083.                 Error = eFileLoadDiskError;
  1084.              FailurePoint6:
  1085.                 goto FailurePoint5;
  1086.             }
  1087.         AlgoSampObj->SavedWindowHeight = SignedShort;
  1088.  
  1089.         /*   4-bytes little endian name length descriptor */
  1090.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1091.             {
  1092.                 Error = eFileLoadDiskError;
  1093.              FailurePoint7:
  1094.                 goto FailurePoint6;
  1095.             }
  1096.         if (SignedLong < 0)
  1097.             {
  1098.                 Error = eFileLoadBadFormat;
  1099.              FailurePoint8:
  1100.                 goto FailurePoint7;
  1101.             }
  1102.  
  1103.         /*   n-bytes name string (line feed = 0x0a) */
  1104.         AlgoSampObj->Name = AllocPtrCanFail(SignedLong,"AlgoSampObjectRec:  name");
  1105.         if (AlgoSampObj->Name == NIL)
  1106.             {
  1107.                 Error = eFileLoadOutOfMemory;
  1108.              FailurePoint9:
  1109.                 goto FailurePoint8;
  1110.             }
  1111.         if (!ReadBufferedInput(Input,SignedLong,AlgoSampObj->Name))
  1112.             {
  1113.                 Error = eFileLoadDiskError;
  1114.              FailurePoint10:
  1115.                 ReleasePtr(AlgoSampObj->Name);
  1116.                 goto FailurePoint9;
  1117.             }
  1118.  
  1119.         /*   4-bytes little endian formula length descriptor */
  1120.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1121.             {
  1122.                 Error = eFileLoadDiskError;
  1123.              FailurePoint11:
  1124.                 goto FailurePoint10;
  1125.             }
  1126.         if (SignedLong < 0)
  1127.             {
  1128.                 Error = eFileLoadBadFormat;
  1129.              FailurePoint12:
  1130.                 goto FailurePoint11;
  1131.             }
  1132.  
  1133.         /*   n-bytes formula string (line feed = 0x0a) */
  1134.         AlgoSampObj->AlgoSampFormula = AllocPtrCanFail(SignedLong,
  1135.             "AlgoSampObjectRec:  formula");
  1136.         if (AlgoSampObj->AlgoSampFormula == NIL)
  1137.             {
  1138.                 Error = eFileLoadOutOfMemory;
  1139.              FailurePoint13:
  1140.                 goto FailurePoint12;
  1141.             }
  1142.         if (!ReadBufferedInput(Input,SignedLong,AlgoSampObj->AlgoSampFormula))
  1143.             {
  1144.                 Error = eFileLoadDiskError;
  1145.              FailurePoint14:
  1146.                 ReleasePtr(AlgoSampObj->AlgoSampFormula);
  1147.                 goto FailurePoint13;
  1148.             }
  1149.  
  1150.         /*   1-byte number of bits */
  1151.         /*       should be 8 or 16 */
  1152.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1153.             {
  1154.                 Error = eFileLoadDiskError;
  1155.              FailurePoint15:
  1156.                 goto FailurePoint14;
  1157.             }
  1158.         if (UnsignedChar == 8)
  1159.             {
  1160.                 AlgoSampObj->NumBits = eSample8bit;
  1161.             }
  1162.         else if (UnsignedChar == 16)
  1163.             {
  1164.                 AlgoSampObj->NumBits = eSample16bit;
  1165.             }
  1166.         else
  1167.             {
  1168.                 Error = eFileLoadBadFormat;
  1169.              FailurePoint16:
  1170.                 goto FailurePoint15;
  1171.             }
  1172.  
  1173.         /*   1-byte number of channels */
  1174.         /*       1 = mono */
  1175.         /*       2 = stereo */
  1176.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  1177.             {
  1178.                 Error = eFileLoadDiskError;
  1179.              FailurePoint17:
  1180.                 goto FailurePoint16;
  1181.             }
  1182.         if (UnsignedChar == 1)
  1183.             {
  1184.                 AlgoSampObj->NumChannels = eSampleMono;
  1185.             }
  1186.         else if (UnsignedChar == 2)
  1187.             {
  1188.                 AlgoSampObj->NumChannels = eSampleStereo;
  1189.             }
  1190.         else
  1191.             {
  1192.                 Error = eFileLoadBadFormat;
  1193.              FailurePoint18:
  1194.                 goto FailurePoint17;
  1195.             }
  1196.  
  1197.         /*   4-bytes little endian sample origin */
  1198.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1199.             {
  1200.                 Error = eFileLoadDiskError;
  1201.              FailurePoint19:
  1202.                 goto FailurePoint18;
  1203.             }
  1204.         AlgoSampObj->Origin = SignedLong;
  1205.  
  1206.         /*   4-bytes little endian loop 1 start point */
  1207.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1208.             {
  1209.                 Error = eFileLoadDiskError;
  1210.              FailurePoint20:
  1211.                 goto FailurePoint19;
  1212.             }
  1213.         AlgoSampObj->LoopStart1 = SignedLong;
  1214.  
  1215.         /*   4-bytes little endian loop 1 end point */
  1216.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1217.             {
  1218.                 Error = eFileLoadDiskError;
  1219.              FailurePoint21:
  1220.                 goto FailurePoint20;
  1221.             }
  1222.         AlgoSampObj->LoopEnd1 = SignedLong;
  1223.  
  1224.         /*   4-bytes little endian loop 2 start point */
  1225.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1226.             {
  1227.                 Error = eFileLoadDiskError;
  1228.              FailurePoint22:
  1229.                 goto FailurePoint21;
  1230.             }
  1231.         AlgoSampObj->LoopStart2 = SignedLong;
  1232.  
  1233.         /*   4-bytes little endian loop 2 end point */
  1234.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1235.             {
  1236.                 Error = eFileLoadDiskError;
  1237.              FailurePoint23:
  1238.                 goto FailurePoint22;
  1239.             }
  1240.         AlgoSampObj->LoopEnd2 = SignedLong;
  1241.  
  1242.         /*   4-bytes little endian loop 3 start point */
  1243.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1244.             {
  1245.                 Error = eFileLoadDiskError;
  1246.              FailurePoint24:
  1247.                 goto FailurePoint23;
  1248.             }
  1249.         AlgoSampObj->LoopStart3 = SignedLong;
  1250.  
  1251.         /*   4-bytes little endian loop 3 end point */
  1252.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1253.             {
  1254.                 Error = eFileLoadDiskError;
  1255.              FailurePoint25:
  1256.                 goto FailurePoint24;
  1257.             }
  1258.         AlgoSampObj->LoopEnd3 = SignedLong;
  1259.  
  1260.         /*   4-bytes little endian sampling rate */
  1261.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1262.             {
  1263.                 Error = eFileLoadDiskError;
  1264.              FailurePoint26:
  1265.                 goto FailurePoint25;
  1266.             }
  1267.         if (SignedLong < MINSAMPLINGRATE)
  1268.             {
  1269.                 SignedLong = MINSAMPLINGRATE;
  1270.             }
  1271.         if (SignedLong > MAXSAMPLINGRATE)
  1272.             {
  1273.                 SignedLong = MAXSAMPLINGRATE;
  1274.             }
  1275.         AlgoSampObj->SamplingRate = SignedLong;
  1276.  
  1277.         /*   4-byte little endian natural frequency fractional portion */
  1278.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1279.         if (!ReadBufferedUnsignedLongLittleEndian(Input,&UnsignedLong))
  1280.             {
  1281.                 Error = eFileLoadDiskError;
  1282.              FailurePoint27:
  1283.                 goto FailurePoint26;
  1284.             }
  1285.         AlgoSampObj->NaturalFrequency = (double)UnsignedLong / 4294967296.0L;
  1286.  
  1287.         /*   4-byte little endian natural frequency integer portion */
  1288.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  1289.             {
  1290.                 Error = eFileLoadDiskError;
  1291.              FailurePoint28:
  1292.                 goto FailurePoint27;
  1293.             }
  1294.         AlgoSampObj->NaturalFrequency += SignedLong;
  1295.         if (AlgoSampObj->NaturalFrequency < MINNATURALFREQ)
  1296.             {
  1297.                 AlgoSampObj->NaturalFrequency = MINNATURALFREQ;
  1298.             }
  1299.         if (AlgoSampObj->NaturalFrequency > MAXNATURALFREQ)
  1300.             {
  1301.                 AlgoSampObj->NaturalFrequency = MAXNATURALFREQ;
  1302.             }
  1303.  
  1304.         /* fill in the other fields */
  1305.         AlgoSampObj->DataModified = False;
  1306.         AlgoSampObj->NeedsToBeRebuilt = True;
  1307.         AlgoSampObj->SampleData = NIL;
  1308.         AlgoSampObj->AlgoSampWindow = NIL;
  1309.         AlgoSampObj->CodeCenter = CodeCenter;
  1310.         AlgoSampObj->MainWindow = MainWindow;
  1311.         AlgoSampObj->AlgoSampList = AlgoSampList;
  1312.  
  1313.         *ObjectOut = AlgoSampObj;
  1314.         return eFileLoadNoError;
  1315.     }
  1316.  
  1317.  
  1318. /* write the object out to the specified file. */
  1319. FileLoadingErrors            AlgoSampObjectWriteOutData(AlgoSampObjectRec* AlgoSampObj,
  1320.                                                 struct BufferedOutputRec* Output)
  1321.     {
  1322.         char*                                StringTemp;
  1323.         double                            NaturalFreqTemp;
  1324.  
  1325.         CheckPtrExistence(AlgoSampObj);
  1326.         CheckPtrExistence(Output);
  1327.  
  1328.         /*   1-byte format version number */
  1329.         /*       should be 1 */
  1330.         if (!WriteBufferedUnsignedChar(Output,1))
  1331.             {
  1332.                 return eFileLoadDiskError;
  1333.             }
  1334.  
  1335.         /*   2-bytes little endian window X location (signed, origin at top-left corner) */
  1336.         /* if the window is open when we save, the most recent coordinates of the */
  1337.         /* window will not be used */
  1338.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowXLoc))
  1339.             {
  1340.                 return eFileLoadDiskError;
  1341.             }
  1342.  
  1343.         /*   2-bytes little endian window Y location */
  1344.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowYLoc))
  1345.             {
  1346.                 return eFileLoadDiskError;
  1347.             }
  1348.  
  1349.         /*   2-bytes little endian window width */
  1350.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowWidth))
  1351.             {
  1352.                 return eFileLoadDiskError;
  1353.             }
  1354.  
  1355.         /*   2-bytes little endian window height */
  1356.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoSampObj->SavedWindowHeight))
  1357.             {
  1358.                 return eFileLoadDiskError;
  1359.             }
  1360.  
  1361.         /*   4-bytes little endian name length descriptor */
  1362.         StringTemp = AlgoSampObjectGetNameCopy(AlgoSampObj);
  1363.         if (StringTemp == NIL)
  1364.             {
  1365.                 return eFileLoadOutOfMemory;
  1366.             }
  1367.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1368.             {
  1369.                 ReleasePtr(StringTemp);
  1370.                 return eFileLoadDiskError;
  1371.             }
  1372.  
  1373.         /*   n-bytes name string (line feed = 0x0a) */
  1374.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1375.             {
  1376.                 ReleasePtr(StringTemp);
  1377.                 return eFileLoadDiskError;
  1378.             }
  1379.         ReleasePtr(StringTemp);
  1380.  
  1381.         /*   4-bytes little endian formula length descriptor */
  1382.         StringTemp = AlgoSampObjectGetFormulaCopy(AlgoSampObj);
  1383.         if (StringTemp == NIL)
  1384.             {
  1385.                 return eFileLoadOutOfMemory;
  1386.             }
  1387.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  1388.             {
  1389.                 ReleasePtr(StringTemp);
  1390.                 return eFileLoadDiskError;
  1391.             }
  1392.  
  1393.         /*   n-bytes formula string (line feed = 0x0a) */
  1394.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  1395.             {
  1396.                 ReleasePtr(StringTemp);
  1397.                 return eFileLoadDiskError;
  1398.             }
  1399.         ReleasePtr(StringTemp);
  1400.  
  1401.         /*   1-byte number of bits */
  1402.         /*       should be 8 or 16 */
  1403.         switch (AlgoSampObjectGetNumBits(AlgoSampObj))
  1404.             {
  1405.                 default:
  1406.                     EXECUTE(PRERR(ForceAbort,"AlgoSampObjectWriteOutData:  bad num bits"));
  1407.                     break;
  1408.                 case eSample8bit:
  1409.                     if (!WriteBufferedUnsignedChar(Output,8))
  1410.                         {
  1411.                             return eFileLoadDiskError;
  1412.                         }
  1413.                     break;
  1414.                 case eSample16bit:
  1415.                     if (!WriteBufferedUnsignedChar(Output,16))
  1416.                         {
  1417.                             return eFileLoadDiskError;
  1418.                         }
  1419.                     break;
  1420.             }
  1421.  
  1422.         /*   1-byte number of channels */
  1423.         /*       1 = mono */
  1424.         /*       2 = stereo */
  1425.         switch (AlgoSampObjectGetNumChannels(AlgoSampObj))
  1426.             {
  1427.                 default:
  1428.                     EXECUTE(PRERR(ForceAbort,"AlgoSampObjectWriteOutData:  bad num channels"));
  1429.                     break;
  1430.                 case eSampleMono:
  1431.                     if (!WriteBufferedUnsignedChar(Output,1))
  1432.                         {
  1433.                             return eFileLoadDiskError;
  1434.                         }
  1435.                     break;
  1436.                 case eSampleStereo:
  1437.                     if (!WriteBufferedUnsignedChar(Output,2))
  1438.                         {
  1439.                             return eFileLoadDiskError;
  1440.                         }
  1441.                     break;
  1442.             }
  1443.  
  1444.         /*   4-bytes little endian sample origin */
  1445.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1446.             AlgoSampObjectGetOrigin(AlgoSampObj)))
  1447.             {
  1448.                 return eFileLoadDiskError;
  1449.             }
  1450.  
  1451.         /*   4-bytes little endian loop 1 start point */
  1452.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1453.             AlgoSampObjectGetLoopStart1(AlgoSampObj)))
  1454.             {
  1455.                 return eFileLoadDiskError;
  1456.             }
  1457.  
  1458.         /*   4-bytes little endian loop 1 end point */
  1459.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1460.             AlgoSampObjectGetLoopEnd1(AlgoSampObj)))
  1461.             {
  1462.                 return eFileLoadDiskError;
  1463.             }
  1464.  
  1465.         /*   4-bytes little endian loop 2 start point */
  1466.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1467.             AlgoSampObjectGetLoopStart2(AlgoSampObj)))
  1468.             {
  1469.                 return eFileLoadDiskError;
  1470.             }
  1471.  
  1472.         /*   4-bytes little endian loop 2 end point */
  1473.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1474.             AlgoSampObjectGetLoopEnd2(AlgoSampObj)))
  1475.             {
  1476.                 return eFileLoadDiskError;
  1477.             }
  1478.  
  1479.         /*   4-bytes little endian loop 3 start point */
  1480.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1481.             AlgoSampObjectGetLoopStart3(AlgoSampObj)))
  1482.             {
  1483.                 return eFileLoadDiskError;
  1484.             }
  1485.  
  1486.         /*   4-bytes little endian loop 3 end point */
  1487.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1488.             AlgoSampObjectGetLoopEnd3(AlgoSampObj)))
  1489.             {
  1490.                 return eFileLoadDiskError;
  1491.             }
  1492.  
  1493.         /*   4-bytes little endian sampling rate */
  1494.         /*       should be between 100 and 65535 */
  1495.         if (!WriteBufferedSignedLongLittleEndian(Output,
  1496.             AlgoSampObjectGetSamplingRate(AlgoSampObj)))
  1497.             {
  1498.                 return eFileLoadDiskError;
  1499.             }
  1500.  
  1501.         /*   4-byte little endian natural frequency fractional portion */
  1502.         /*       unsigned; divide by 2^32 to get the actual fraction */
  1503.         NaturalFreqTemp = AlgoSampObjectGetNaturalFrequency(AlgoSampObj);
  1504.         if (!WriteBufferedUnsignedLongLittleEndian(Output,
  1505.             (unsigned long)((NaturalFreqTemp - (long)NaturalFreqTemp) * 4294967296.0L)))
  1506.             {
  1507.                 return eFileLoadDiskError;
  1508.             }
  1509.  
  1510.         /*   4-byte little endian natural frequency integer portion */
  1511.         /*       total natural frequency should be between 0.01 and 1e6 */
  1512.         if (!WriteBufferedSignedLongLittleEndian(Output,(long)NaturalFreqTemp))
  1513.             {
  1514.                 return eFileLoadDiskError;
  1515.             }
  1516.  
  1517.         return eFileLoadNoError;
  1518.     }
  1519.  
  1520.  
  1521. /* mark the object as saved */
  1522. void                                    AlgoSampObjectMarkAsSaved(AlgoSampObjectRec* AlgoSampObj)
  1523.     {
  1524.         CheckPtrExistence(AlgoSampObj);
  1525.         if (AlgoSampObj->AlgoSampWindow != NIL)
  1526.             {
  1527.                 AlgoSampWindowWritebackModifiedData(AlgoSampObj->AlgoSampWindow);
  1528.             }
  1529.         AlgoSampObj->DataModified = False;
  1530.     }
  1531.